[ESP8266]空气检测器

Talk is cheap, show me the codes.

瞎鸡儿写的一个用ESP8266开发板和SenseAir S8二氧化碳传感器, PMS5003ST做MQTT空气传感器的东西(病句警告)

pms的代码是基于gayhub上改的

由于是瞎写的所以代码逻辑混乱
放出来是因为闲的没事干

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "pms5003ST.h"

#define S8_RXPIN D6
#define S8_TXPIN D5
#define PMS_RXPIN D2
//#define DT_RXPIN D5
//#define DT_TXPIN D6

SoftwareSerial S8(S8_RXPIN, S8_TXPIN);
SoftwareSerial PMS_Serial(PMS_RXPIN, D0);
//SoftwareSerial Data_Serial(DT_RXPIN, DT_TXPIN);
PMS::DATA pms_data;
PMS pms(PMS_Serial);

const char *ssid = "Wireless-2.4Ghz";
const char *passwd = "83885877";
const char *mqtt_server = "192.168.0.2";
const char *mqtt_name = "disktation";

WiFiClient espClient;
PubSubClient client(espClient);

long lastMsg = 0;
char msg[128];


/* CO2 */
byte command_read_co2[] = {
0xFE, 0x44, 0x00, 0x08, 0x02, 0x9F, 0x25
};
byte response[] = {0, 0, 0, 0, 0, 0, 0};
int co2_value_scale = 1;
unsigned long co2 = 0;

bool co2_send_command(Stream *serial = &S8,
byte *cmd = command_read_co2,
int cmd_len = 7,
byte *resp = response,
int resp_len = 7) {
while (!serial->available()) {
serial->write(cmd, cmd_len);
delay(50);
}

int timeout = 0;
while (serial->available() < 7) {
timeout++;
if (timeout > 10) {
while (serial->available())
serial->read();
return false;
}
delay(50);
}
for (int i = 0; i < resp_len; i++)
resp[i] = serial->read();
return true;
}

unsigned long co2_read_response(byte *resp = response, int scale = co2_value_scale) {
return scale * (resp[3] * 256 + resp[4]);
}

/* Repackage */

bool send_using_serial(Stream *serial, unsigned long co2, PMS::DATA *pms) {
bool sent = false;
while (serial->available()) {
serial->read();
}
if (!serial->available()) {
// Recog code
serial->write(0xAD);
serial->write(0x01);
// CO2 data
serial->write(0xD1);
serial->write((byte*)&co2, sizeof(co2));
// pms data
serial->write(0xD2);
serial->write((byte*)pms, sizeof(PMS::DATA));
// EndofData
serial->write(0xF1);
serial->write(0xF1);
sent = true;
}
return sent;
}

/* Network */
void setup_wifi() {
delay(100);
Serial.println("WiFi connecting...");
WiFi.begin(ssid, passwd);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Failed! Rebooting...");
delay(5000);
ESP.restart();
}
Serial.println("WiFi Connected.");
delay(500);
Serial.print("IP Addr: ");
Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Command is : [");
Serial.print(topic);
int p = (char)payload[0] - '0';

if (p == 0) {
Serial.println("to show humidity!]");
}

if (p == 1) {
// digitalWrite(BUILTIN_LED, HIGH);
Serial.println(" is to show temperature!] ");
}
Serial.println();
} //end callback

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
if (client.connect(clientId.c_str())) {
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe("OsoyooCommand");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()

void setup() {
Serial.begin(9600);
Serial.println("Initialization --Begin--");
// Actual init process;
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
Serial.println("Initialization --Done--");
}

void publish_it(unsigned long value, const char *name) {
char addr_buf[32];
sprintf(addr_buf, "Air/%s", name);
char buf[32];
sprintf(buf, "%ld", value);
if (client.publish(addr_buf, buf))
Serial.println("ed!");
else
Serial.println(" Failed...");
}

void publish_it_float(float value, const char *name, int dig) {
char addr_buf[32];
sprintf(addr_buf, "Air/%s", name);
char buf[32];
sprintf(buf, "%.*f", dig, value);
if (client.publish(addr_buf, buf))
Serial.println("ed!");
else
Serial.println(" Failed...");
}

void loop() {
// put your main code here, to run repeatedly:
/*
Data_Serial.begin(9600);
//send_using_serial(&Data_Serial, co2, &pms_data);
delay(5000);
if(Data_Serial.available())
Data_Serial.println("Hello!");
Data_Serial.end();
Serial.println("Sent.");
*/
if (!client.connected())
reconnect();
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
// Read co2
S8.begin(9600);
S8.flush();
co2 = 0;
if (co2_send_command()) {
co2 = co2_read_response();
Serial.println(co2);
}
S8.end();

// Read pms
PMS_Serial.begin(9600);
PMS_Serial.flush();
if (pms.read(pms_data, 5000)) {
Serial.println((float)pms_data.TEMP / 10.0f);
} else {
memset(&pms_data, 0, sizeof(PMS::DATA));
}

publish_it(co2, "CO2");
publish_it_float(pms_data.TEMP / 10.0f, "TEMP", 1);
publish_it_float(pms_data.HCHO / 1000.0f, "HCHO", 3);
publish_it_float(pms_data.HUMD / 10.0f, "HUMD", 1);
publish_it(pms_data.PM_FE_UG_1_0, "PM1.0-FE");
publish_it(pms_data.PM_FE_UG_2_5, "PM2.5-FE");
publish_it(pms_data.PM_FE_UG_10_0, "PM10-FT");
publish_it(pms_data.PM_AE_UG_1_0, "PM2.5");
publish_it(pms_data.PM_AE_UG_2_5, "PM2.5");
publish_it(pms_data.PM_AE_UG_10_0, "PM10");
publish_it(pms_data.ABOVE_0dot3_um, ">0.3um");
publish_it(pms_data.ABOVE_0dot5_um, ">0.5um");
publish_it(pms_data.ABOVE_1dot0_um, ">1.0um");
publish_it(pms_data.ABOVE_2dot5_um, ">2.5um");
publish_it(pms_data.ABOVE_5dot0_um, ">5.0um");
publish_it(pms_data.ABOVE_10_um, ">10um");

PMS_Serial.end();
}
}

pms5003ST.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#ifndef PMS_H
#define PMS_H

#include "Stream.h"

class PMS
{
public:
struct DATA {
// Factory environment
uint16_t PM_FE_UG_1_0;
uint16_t PM_FE_UG_2_5;
uint16_t PM_FE_UG_10_0;

// Atmospheric environment
uint16_t PM_AE_UG_1_0;
uint16_t PM_AE_UG_2_5;
uint16_t PM_AE_UG_10_0;

// ST
uint16_t ABOVE_0dot3_um;
uint16_t ABOVE_0dot5_um;
uint16_t ABOVE_1dot0_um;
uint16_t ABOVE_2dot5_um;
uint16_t ABOVE_5dot0_um;
uint16_t ABOVE_10_um;

// ST 2
uint16_t HCHO;
uint16_t TEMP;
uint16_t HUMD;
};

enum STATUS { STATUS_WAITING, STATUS_OK };

PMS(Stream&);

bool read(DATA& data, uint16_t timeout = 0);

private:
uint8_t _payload[30];
Stream* _stream;
DATA* _data;
STATUS _status;

uint8_t _index = 0;
uint16_t _frameLen;
uint16_t _checksum;
uint16_t _calculatedChecksum;

void loop();
};

#endif

pms5003ST.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "Arduino.h"
#include "pms5003ST.h"

PMS::PMS(Stream& stream)
{
this->_stream = &stream;
}

// Non-blocking function for parse response.
// If you want to wait for the full response (blocking), specify timeout parameter (1000ms is sufficient). This makes it easier to work in passive mode.
bool PMS::read(DATA& data, uint16_t timeout)
{
_data = &data;
if (timeout > 0)
{
uint32_t start = millis();
do
{
loop();
if (_status == STATUS_OK) break;
} while (millis() - start < timeout);
}
else
{
loop();
}

return _status == STATUS_OK;
}

void PMS::loop()
{
_status = STATUS_WAITING;
if (_stream->available())
{
uint8_t ch = _stream->read();

switch (_index)
{
case 0:
if (ch != 0x42)
{
return;
}
_calculatedChecksum = ch;
break;

case 1:
if (ch != 0x4D)
{
_index = 0;
return;
}
_calculatedChecksum += ch;
break;

case 2:
_calculatedChecksum += ch;
_frameLen = ch << 8;
break;

case 3:
_frameLen |= ch;
// Unsupported sensor, different frame length, transmission error e.t.c.
if (_frameLen != 2 * 17 + 2)
{
_index = 0;
return;
}
_calculatedChecksum += ch;
break;

default:
if (_index == _frameLen + 2)
{
_checksum = ch << 8;
}
else if (_index == _frameLen + 2 + 1)
{
_checksum |= ch;

if (_calculatedChecksum == _checksum)
{
_status = STATUS_OK;

// Factory environment.
_data->PM_FE_UG_1_0 = makeWord(_payload[0], _payload[1]);
_data->PM_FE_UG_2_5 = makeWord(_payload[2], _payload[3]);
_data->PM_FE_UG_10_0 = makeWord(_payload[4], _payload[5]);

// Atmospheric environment.
_data->PM_AE_UG_1_0 = makeWord(_payload[6], _payload[7]);
_data->PM_AE_UG_2_5 = makeWord(_payload[8], _payload[9]);
_data->PM_AE_UG_10_0 = makeWord(_payload[10], _payload[11]);

_data->ABOVE_0dot3_um = makeWord(_payload[12], _payload[13]);
_data->ABOVE_0dot5_um = makeWord(_payload[14], _payload[15]);
_data->ABOVE_1dot0_um = makeWord(_payload[16], _payload[17]);
_data->ABOVE_2dot5_um = makeWord(_payload[18], _payload[19]);
_data->ABOVE_5dot0_um = makeWord(_payload[20], _payload[21]);
_data->ABOVE_10_um = makeWord(_payload[22], _payload[23]);

_data->HCHO = makeWord(_payload[24], _payload[25]);
_data->TEMP = makeWord(_payload[26], _payload[27]);
_data->HUMD = makeWord(_payload[28], _payload[29]);
}

_index = 0;
return;
}
else
{
_calculatedChecksum += ch;
uint8_t payloadIndex = _index - 4;

// Payload is common to all sensors (first 2x6 bytes).
if (payloadIndex < sizeof(_payload))
{
_payload[payloadIndex] = ch;
}
}

break;
}

_index++;
}
}